﻿#Region "License & Usage"

'Microsoft Public License (Ms-PL) 

'This license governs use of the accompanying software. If you use the 
'software, you accept this license. If you do not accept the license, do 
'not use the software. 

'1. Definitions 

'The terms "reproduce," "reproduction," "derivative works," and 
'"distribution" have the same meaning here as under U.S. copyright law. 

'A "contribution" is the original software, or any additions or changes 
'to the software. 

'A "contributor" is any person that distributes its contribution under 
'this license. 

'"Licensed patents" are a contributor's patent claims that read directly 
'on its contribution. 

'2. Grant of Rights 

'(A) Copyright Grant- Subject to the terms of this license, including the 
'license conditions and limitations in section 3, each contributor grants 
'you a non-exclusive, worldwide, royalty-free copyright license to 
'reproduce its contribution, prepare derivative works of its 
'contribution, and distribute its contribution or any derivative works 
'that you create. 

'(B) Patent Grant- Subject to the terms of this license, including the 
'license conditions and limitations in section 3, each contributor grants 
'you a non-exclusive, worldwide, royalty-free license under its licensed 
'patents to make, have made, use, sell, offer for sale, import, and/or 
'otherwise dispose of its contribution in the software or derivative 
'works of the contribution in the software. 

'3. Conditions and Limitations 

'(A) No Trademark License- This license does not grant you rights to use 
'any contributors' name, logo, or trademarks. 

'(B) If you bring a patent claim against any contributor over patents 
'that you claim are infringed by the software, your patent license from 
'such contributor to the software ends automatically. 

'(C) If you distribute any portion of the software, you must retain all 
'copyright, patent, trademark, and attribution notices that are present 
'in the software. 

'(D) If you distribute any portion of the software in source code form, 
'you may do so only under this license by including a complete copy of 
'this license with your distribution. If you distribute any portion of 
'the software in compiled or object code form, you may only do so under a 
'license that complies with this license. 

'(E) The software is licensed "as-is." You bear the risk of using it. The 
'contributors give no express warranties, guarantees or conditions. You 
'may have additional consumer rights under your local laws which this 
'license cannot change. To the extent permitted under your local laws, 
'the contributors exclude the implied warranties of merchantability, 
'fitness for a particular purpose and non-infringement.

#End Region

#Region "Code Refered From"
'Most of the code is refered from this program. I have rewritten most of the part for Windows Mobile.
'Title: Visal: Histogram v0.1
'Description: Visal: Histogram might not be the best .NET histogram custom, but it is very flexible histogram control that allow user to customize almost on every aspect of its look.
'This file came from Planet-Source-Code.com...the home millions of lines of source code
'You can view comments on this code/and or vote on it at: http://www.Planet-Source-Code.com/vb/scripts/ShowCode.asp?txtCodeId=7822&lngWId=10
#End Region

#Region "Options"

Option Strict On
Option Explicit On

#End Region

#Region "Imports"

'From .Net Framework 3.5
Imports Microsoft.Drawing
Imports System.Drawing
Imports System.IO
Imports System.Windows.Forms

'From Custom Classes/Reference
Imports StedySoft.SenseSDK
Imports StedySoft.SenseSDK.DrawingCE
Imports SenseSDKExtended.DrawingCEEx

#End Region

Namespace SensePanelHistogram

    Public Class Style1
        Inherits SensePanelBase
        Implements IDisposable

#Region "Others"

        'General Flags
        Private _disposed As Boolean = False

        ''' <summary>
        ''' Dispose
        ''' </summary>
        ''' <remarks>None</remarks>
        Public Overrides Sub Dispose()

            Try

                Me._dispose(True)
                GC.SuppressFinalize(Me)
                MyBase.Dispose()

            Catch ex As Exception

                'Throw exception if any other error caught
                Throw New Exception(ex.Message)

            End Try

        End Sub

        ''' <summary>
        ''' _Dispose
        ''' </summary>
        ''' <param name="disposing"></param>
        ''' <remarks>None</remarks>
        Private Sub _dispose(ByVal disposing As Boolean)

            Try

                If _saveFileAllow Then

                    If (Not Me._disposed) Then
                        If (disposing) Then
                            If System.IO.File.Exists(_fileName) Then
                                System.IO.File.Delete(_fileName)
                            End If
                        End If
                    End If

                End If

                Me._disposed = True

            Catch ex As Exception

                'Throw exception if any other error caught
                Throw New Exception(ex.Message)

            End Try
        End Sub

        Public Enum HistogramLayerStyle
            None = 0
            HorizontalStripe = 1
        End Enum

        Public WithEvents Title As HistogramCaption = New HistogramCaption("Unnamed Histogram", New Font("Tahoma", 7, FontStyle.Regular), Color.Black)
        Public WithEvents XAxisTitle As HistogramCaption = New HistogramCaption("X Axis", New Font("Tahoma", 7, FontStyle.Regular), Color.Black)
        Public WithEvents YAxisTitle As HistogramCaption = New HistogramCaption("Y Axis", New Font("Tahoma", 7, FontStyle.Regular), Color.Black)
        Public WithEvents Data As HistogramData = New HistogramData()

        Private XAxisMin As Single = 0
        Private XAxisMax As Single = 100
        Private XAxisInt As Single = 10

        Private BkColor1 As Color = Color.WhiteSmoke

        Private YAxisMin As Single = 0
        Private YAxisMax As Single = 100
        Private YAxisInt As Single = 25

        Private _LayerStyle As HistogramLayerStyle = HistogramLayerStyle.HorizontalStripe

        Private Sub Title_Change() Handles Title.Change
            Invalidate()
        End Sub

        Private Sub XAxisTitle_Change() Handles XAxisTitle.Change
            Invalidate()
        End Sub

        Private Sub YAxisTitle_Change() Handles YAxisTitle.Change
            Invalidate()
        End Sub

        Private Sub Data_Change() Handles Data.Change
            Invalidate()
        End Sub


        Public Property BackgroundColor1() As Color
            Get
                Return BkColor1
            End Get
            Set(ByVal value As Color)
                BkColor1 = value
                Invalidate()
            End Set
        End Property

        Public Property LayerStyle() As HistogramLayerStyle
            Get
                Return _LayerStyle
            End Get
            Set(ByVal value As HistogramLayerStyle)
                _LayerStyle = value
                Invalidate()
            End Set
        End Property

        Public Property XAxisMinimum() As Single
            Get
                Return XAxisMin
            End Get
            Set(ByVal value As Single)
                XAxisMin = value
                Invalidate()
            End Set
        End Property

        Public Property XAxisMaximum() As Single
            Get
                Return XAxisMax
            End Get
            Set(ByVal value As Single)
                XAxisMax = value
                Invalidate()
            End Set
        End Property

        Public Property XAxisInterval() As Single
            Get
                Return XAxisInt
            End Get
            Set(ByVal value As Single)
                XAxisInt = value
                Invalidate()
            End Set
        End Property

        Public Property YAxisMinimum() As Single
            Get
                Return YAxisMin
            End Get
            Set(ByVal value As Single)
                YAxisMin = value
                Invalidate()
            End Set
        End Property


        Public Property YAxisMaximum() As Single
            Get
                Return YAxisMax
            End Get
            Set(ByVal value As Single)
                YAxisMax = value
                Invalidate()
            End Set
        End Property

        Public Property YAxisInterval() As Single
            Get
                Return YAxisInt
            End Get
            Set(ByVal value As Single)
                YAxisInt = value
                Invalidate()
            End Set
        End Property

        Private _saveFileAllow As Boolean = False

        Public Property SaveFileAllow() As Boolean
            Get
                Return _saveFileAllow
            End Get
            Set(ByVal value As Boolean)
                _saveFileAllow = value
            End Set
        End Property

#End Region

        Public Event OnFileGenerated As OnFileGeneratedEventHandler

        Public Delegate Sub OnFileGeneratedEventHandler(ByVal sender As Object, ByVal filepath As String)

        Private _controlRegion As Rectangle = Nothing

        Private _titleRectangle As Rectangle = Nothing
        Private _titleSize As Size = Nothing

        Private _xAxisTitleRectangle As Rectangle = Nothing
        Private _xAxisTitleSize As Size = Nothing

        Private _yAxisTitleRectangle As Rectangle = Nothing
        Private _yAxisTitleSize As Size = Nothing

        Private _graphRegionRectangle As Rectangle = Nothing
        Private _graphRegionSize As Size = Nothing

        Private _fileName As String = Nothing
        Private _tempPath As String = System.IO.Path.GetTempPath
        Private iimg_bg As IImage = Nothing
        Private _graphGenerated As Boolean = False

        ''' <summary>
        ''' Check if it is VGA or QVGA
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Function _isVGA() As Boolean

            Try

                'Return the output
                Return StedySoft.SenseSDK.DrawingCE.Resolution.ScreenIsVGA

            Catch ex As Exception

                'Throw exception if any other error caught
                Throw New Exception(ex.Message)

            End Try

        End Function

        Public Overrides Sub OnRender(ByVal g As System.Drawing.Graphics)
            MyBase.OnRender(g)

            'Check if Graph is already generated, if yes then use that else create it again.
            If Not _graphGenerated Then
                CreateGraphics()
            End If

            'Display the graph
            g.DrawImageAlphaChannel(iimg_bg, New Rectangle(ClientRectangle.Left, ClientRectangle.Top, ClientRectangle.Width, ClientRectangle.Height))

        End Sub

        Public Sub CreateGraphics()

            '########################################### Create Graphics Object ###########################################

            'Create a blank bitmap image
            Dim _graphImage As New Bitmap(StedySoft.SenseSDK.DrawingCE.Resolution.ScreenWidth, ClientRectangle.Height)
            'Add the bitmap to Graphics object
            Dim g As Graphics = Graphics.FromImage(_graphImage)

            '########################################### Create Background Color ##########################################

            'Draw background color
            g.FillRectangle(New SolidBrush(DrawingCE.SenseColors.List_Background), 0, 0, MyBase.Width, ClientRectangle.Height)

            '######################################### Set Various Rectangle Values #######################################

            'Set all values in main control region rectangle
            _controlRegion = New Rectangle(0, 0, ClientRectangle.Width, ClientRectangle.Height)

            'Set size values
            _titleSize = New Size(Screen.PrimaryScreen.Bounds.Width - If(_isVGA, 20, 10), SenseAPIsEx.SenseStrings.CalculateStringHeight(Title.Caption, Title.Font.Name, CInt(Title.Font.Size), Title.Font.Style, New Size(Screen.PrimaryScreen.Bounds.Width, Nothing)))
            _xAxisTitleSize = New Size(Screen.PrimaryScreen.Bounds.Width - If(_isVGA, 20, 10), SenseAPIsEx.SenseStrings.CalculateStringHeight(XAxisTitle.Caption, XAxisTitle.Font.Name, CInt(XAxisTitle.Font.Size), XAxisTitle.Font.Style, New Size(Screen.PrimaryScreen.Bounds.Width, Nothing)))
            _yAxisTitleSize = New Size(Screen.PrimaryScreen.Bounds.Width - If(_isVGA, 20, 10), SenseAPIsEx.SenseStrings.CalculateStringHeight(YAxisTitle.Caption, YAxisTitle.Font.Name, CInt(YAxisTitle.Font.Size), YAxisTitle.Font.Style, New Size(Screen.PrimaryScreen.Bounds.Width, Nothing)))
            _graphRegionSize = New Size(Screen.PrimaryScreen.Bounds.Width - If(_isVGA, 40, 20), ClientRectangle.Height - _titleSize.Height - _xAxisTitleSize.Height - _yAxisTitleSize.Height - If(_isVGA, 40, 20))

            'Set rectangles values
            _titleRectangle = New Rectangle(If(_isVGA, 10, 5), 0, _titleSize.Width, _titleSize.Height)
            _xAxisTitleRectangle = New Rectangle(If(_isVGA, 10, 5), (ClientRectangle.Height - _xAxisTitleSize.Height) - If(_isVGA, 10, 5), _xAxisTitleSize.Width, _xAxisTitleSize.Height)
            _yAxisTitleRectangle = New Rectangle(If(_isVGA, 10, 5), _xAxisTitleSize.Height + If(_isVGA, 10, 5), _yAxisTitleSize.Width, _yAxisTitleSize.Height)
            _graphRegionRectangle = New Rectangle(If(_isVGA, 10, 5), _titleSize.Height + _xAxisTitleSize.Height + If(_isVGA, 20, 10), _graphRegionSize.Width, _graphRegionSize.Height)

            '########################################## Create Title and Captions ##########################################

            If Not Title.Caption = String.Empty Then
                'Draw the Title text with other properties like height,color,style,alignment,etc
                Using f As Font = New Font(Title.Font.Name, CInt(Title.Font.Size), Title.Font.Style)
                    Dim s As String = SenseAPIsEx.SenseStrings.GetTrimmedDottedText(Title.Caption, Title.Font.Name, CInt(Title.Font.Size), Title.Font.Style, New Size(_titleRectangle.Width, _titleRectangle.Height), g)
                    Dim r As Rectangle = New Rectangle(_titleRectangle.Left, _titleRectangle.Top, _titleRectangle.Width, _titleRectangle.Height) '(Left,Top,Width,Height)
                    Using b As Brush = New SolidBrush(Title.FontColor)
                        Using sf As StringFormat = New StringFormat()
                            sf.Alignment = StringAlignment.Center
                            g.DrawString(s, f, b, r, sf)
                        End Using
                    End Using
                End Using
            End If

            If Not XAxisTitle.Caption = String.Empty Then
                'Draw the XAxisTitle text with other properties like height,color,style,alignment,etc
                Using f As Font = New Font(XAxisTitle.Font.Name, CInt(XAxisTitle.Font.Size), XAxisTitle.Font.Style)
                    Dim s As String = SenseAPIsEx.SenseStrings.GetTrimmedDottedText(XAxisTitle.Caption, XAxisTitle.Font.Name, CInt(XAxisTitle.Font.Size), XAxisTitle.Font.Style, New Size(_xAxisTitleRectangle.Width, _xAxisTitleRectangle.Height), g)
                    Dim r As Rectangle = New Rectangle(_xAxisTitleRectangle.Left, _xAxisTitleRectangle.Top, _xAxisTitleRectangle.Width, _xAxisTitleRectangle.Height) '(Left,Top,Width,Height)
                    Using b As Brush = New SolidBrush(XAxisTitle.FontColor)
                        Using sf As StringFormat = New StringFormat()
                            sf.Alignment = StringAlignment.Center
                            g.DrawString(s, f, b, r, sf)
                        End Using
                    End Using
                End Using
            End If

            If Not YAxisTitle.Caption = String.Empty Then
                'Draw the YAxisTitle text with other properties like height,color,style,alignment,etc
                Using f As Font = New Font(YAxisTitle.Font.Name, CInt(YAxisTitle.Font.Size), YAxisTitle.Font.Style)
                    Dim s As String = SenseAPIsEx.SenseStrings.GetTrimmedDottedText(YAxisTitle.Caption, YAxisTitle.Font.Name, CInt(YAxisTitle.Font.Size), YAxisTitle.Font.Style, New Size(_yAxisTitleRectangle.Width, _yAxisTitleRectangle.Height), g)
                    Dim r As Rectangle = New Rectangle(_yAxisTitleRectangle.Left, _yAxisTitleRectangle.Top, _yAxisTitleRectangle.Width, _yAxisTitleRectangle.Height) '(Left,Top,Width,Height)
                    Using b As Brush = New SolidBrush(YAxisTitle.FontColor)
                        Using sf As StringFormat = New StringFormat()
                            sf.Alignment = StringAlignment.Near
                            g.DrawString(s, f, b, r, sf)
                        End Using
                    End Using
                End Using
            End If

            '########################################### Draw X and Y Axis Lines ###########################################

            'Local variables
            Dim WidthPerInterval As Single = Nothing
            Dim Counter As Single = Nothing
            Dim _axisRegion As Rectangle = Nothing
            Dim _strWidth As Integer = 0
            Dim _strMaxWidth As Integer = 0

            'Assign rectangle values for local use
            _axisRegion = _graphRegionRectangle

            'Reserve some spaces for X interval caption
            _axisRegion.Height -= If(_isVGA, 10, 5)

            'Reserve some spaces for Y interval caption
            For i As Single = (YAxisMin + YAxisInt) To YAxisMax Step YAxisInt
                _strWidth = CInt(g.MeasureString(i.ToString(), New Font(YAxisTitle.Font.Name, CInt(YAxisTitle.Font.Size), YAxisTitle.Font.Style)).Width)
                If _strMaxWidth < _strWidth Then
                    _strMaxWidth = _strWidth
                End If
            Next

            'Minus/Add width for axis
            _axisRegion.Width -= _strMaxWidth + If(_isVGA, 6, 3)
            _axisRegion.X += _strMaxWidth + If(_isVGA, 6, 3)

            'Drawing X axis line
            g.DrawLine(New Pen(Color.Black), _axisRegion.Left, _axisRegion.Bottom, _axisRegion.Right, _axisRegion.Bottom)

            'Drawing Y axis line
            g.DrawLine(New Pen(Color.Black), _axisRegion.Left, _axisRegion.Top, _axisRegion.Left, _axisRegion.Bottom)

            '######################################### Draw X and Y Axis Intervals #########################################

            'Draw X Axis interval
            WidthPerInterval = _axisRegion.Width / ((XAxisMax - XAxisMin) / XAxisInt)
            Counter = XAxisMin
            For i As Single = XAxisMin To XAxisMax Step XAxisInt
                g.DrawLine(New Pen(Color.Black), CInt(_axisRegion.Left + Counter), _axisRegion.Bottom - 1, CInt(_axisRegion.Left + Counter),_axisRegion.Bottom + 1)

                'Draw caption on the bottom.
                _strWidth = CInt(g.MeasureString(i.ToString(), New Font(XAxisTitle.Font.Name, CInt(XAxisTitle.Font.Size), XAxisTitle.Font.Style)).Width)
                g.DrawString(i.ToString(), New Font(XAxisTitle.Font.Name, CInt(XAxisTitle.Font.Size), XAxisTitle.Font.Style), New SolidBrush(Color.Black), CSng(_axisRegion.Left + Counter - (_strWidth / 2)), CInt(_axisRegion.Bottom + 5))

                'Find the next interval's X position
                Counter += WidthPerInterval
            Next

            'Draw Y Axis interval
            WidthPerInterval = _axisRegion.Height / ((YAxisMax - YAxisMin) / YAxisInt)
            Counter = YAxisMin
            For i As Single = YAxisMin To YAxisMax Step YAxisInt
                g.DrawLine(New Pen(Color.Black), _axisRegion.Left - 1, CInt(_axisRegion.Bottom - Counter), _axisRegion.Left + 1, CInt(_axisRegion.Bottom - Counter))

                'Draw caption on the left side.
                g.DrawString(i.ToString(), New Font(YAxisTitle.Font.Name, CInt(YAxisTitle.Font.Size), YAxisTitle.Font.Style), New SolidBrush(Color.Black),CSng(_axisRegion.Left - _strMaxWidth - 5),CSng(_axisRegion.Bottom - Counter - (7 / 2)))

                'Find the next interval's X position
                Counter += WidthPerInterval
            Next

            'Update values in _axisRegion
            _axisRegion = New Rectangle(_axisRegion.Left + 1, _axisRegion.Top, _axisRegion.Width - 1, _axisRegion.Height - 1)

            '########################################## Draw Background Bar Layers #########################################

            If _LayerStyle = HistogramLayerStyle.HorizontalStripe Then
                'Reset few variables
                Counter = Nothing
                Dim Switch As Boolean
                WidthPerInterval = Nothing

                WidthPerInterval = _axisRegion.Height / ((YAxisMax - YAxisMin) / YAxisInt)
                Counter = WidthPerInterval
                Switch = True

                For i As Single = (YAxisMin + YAxisInt) To YAxisMax Step YAxisInt
                    If Switch Then
                        g.FillRectangle(New SolidBrush(BkColor1), _axisRegion.Left, CInt(_axisRegion.Bottom - Counter), _axisRegion.Width, CInt(WidthPerInterval))
                    End If
                    Switch = Not Switch
                    Counter += WidthPerInterval
                Next

            End If

            '################################################## Draw Bars ##################################################

            'Declare few variables
            Dim WidthInterval As Single = Nothing
            Dim WidthInterval2 As Single = Nothing
            Dim HeightWidth As Single = Nothing

            For i As Integer = 0 To Data.Data.Count - 1

                WidthInterval = (_axisRegion.Width / (XAxisMax - XAxisMin)) * DirectCast(DirectCast(DirectCast(DirectCast(Data, HistogramData).Data, System.Collections.ArrayList).Item(i), System.Object), HistogramData.Item).Interval

                WidthInterval2 = (_axisRegion.Width / (XAxisMax - XAxisMin)) * DirectCast(DirectCast(DirectCast(DirectCast(Data, HistogramData).Data, System.Collections.ArrayList).Item(i), System.Object), HistogramData.Item).Width

                HeightWidth = (_axisRegion.Height / (YAxisMax - YAxisMin)) * DirectCast(DirectCast(DirectCast(DirectCast(Data, HistogramData).Data, System.Collections.ArrayList).Item(i), System.Object), HistogramData.Item).Value

                'Draw Rectangle borders
                g.DrawRectangle(New Pen(Color.Black, 1), CInt(_axisRegion.Left + WidthInterval), CInt(_axisRegion.Bottom - HeightWidth), CInt(WidthInterval2), CInt(HeightWidth))

                'Fill Rectangles
                g.FillRectangle(New SolidBrush(DirectCast(DirectCast(DirectCast(DirectCast(Data, HistogramData).Data, System.Collections.ArrayList).Item(i), System.Object), HistogramData.Item).Color), CInt(_axisRegion.Left + WidthInterval), CInt(_axisRegion.Bottom - HeightWidth), CInt(WidthInterval2), CInt(HeightWidth))

            Next i

            '################################################## Clean Up ##################################################

            'Dispose Graphics object as we now have got the bitmap
            g.Dispose()

            '################################################ Process Image ###############################################

            'Save file if required
            If _saveFileAllow Then

                _fileName = _tempPath & "SPExHistogram_" & System.Guid.NewGuid.ToString.ToLower.Replace("-", "").Substring(1, 8) & ".png"
                _graphImage.Save(_fileName, System.Drawing.Imaging.ImageFormat.Png)

                RaiseEvent OnFileGenerated(Me, _fileName)

            End If

            Using m As MemoryStream = New MemoryStream
                Dim iimg As IImage = Nothing
                _graphImage.Save(m, System.Drawing.Imaging.ImageFormat.Png)
                ImagingFactory.GetImaging.CreateImageFromBuffer(m.GetBuffer, Convert.ToUInt32(m.Length), BufferDisposalFlag.BufferDisposalFlagNone, iimg)
                _graphImage.Dispose()
                _graphImage = Nothing
                m.Close()
                iimg_bg = iimg
            End Using

            'Mark _graphGenerated as true
            _graphGenerated = True

            '################################################## All Done!! #################################################

        End Sub

        Public Class HistogramData
            Public Structure Item
                Public Interval As Single
                Public Width As Single
                Public Value As Single
                Public Color As Color

                Public Sub New(ByVal _Interval As Single, ByVal _Width As Single, _
                           ByVal _Value As Single, ByVal _Color As Color)
                    Interval = _Interval
                    Width = _Width
                    Value = _Value
                    Color = _Color
                End Sub
            End Structure

            Private _Collection As New ArrayList()
            Public Event Change()

            Public Sub Add(ByVal _Interval As Single, ByVal _Width As Single, _
                           ByVal _Value As Single, ByVal _Color As Color, Optional ByVal Index As Integer = -1)
                If Index < 0 Then
                    _Collection.Add(New Item(_Interval, _Width, _Value, _Color))
                Else
                    _Collection.Insert(Index, New Item(_Interval, _Width, _Value, _Color))
                End If

                RaiseEvent Change()
            End Sub

            Public Sub Remove(ByVal Index As Integer)
                _Collection.RemoveAt(Index)
                RaiseEvent Change()
            End Sub

            Public Sub Clear()
                _Collection.Clear()
                RaiseEvent Change()
            End Sub

            Public Property Data() As ArrayList
                Get
                    Return _Collection
                End Get
                Set(ByVal value As ArrayList)
                    _Collection = value
                End Set
            End Property
        End Class

        Public Class HistogramCaption
            Private _Caption As String
            Private _Font As Font
            Private _FontColor As Color

            Public Event Change()

            Public Sub New(ByVal __Caption As String, ByVal __Font As Font, ByVal __FontColor As Color)
                _Caption = __Caption
                Me._Font = __Font
                _FontColor = __FontColor
            End Sub

            Public Property Caption() As String
                Get
                    Return _Caption
                End Get
                Set(ByVal value As String)
                    _Caption = value
                    RaiseEvent Change()
                End Set
            End Property

            Public Property Font() As Font
                Get
                    Return _Font
                End Get
                Set(ByVal value As Font)
                    _Font = value
                    RaiseEvent Change()
                End Set
            End Property

            Public Property FontColor() As Color
                Get
                    Return _FontColor
                End Get
                Set(ByVal value As Color)
                    _FontColor = value
                    RaiseEvent Change()
                End Set
            End Property

        End Class

    End Class

End Namespace